package com.googlecode.gaal.vis;

import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.io.Writer;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import com.googlecode.gaal.data.api.Corpus;
import com.googlecode.gaal.data.impl.TreeMapCorpus;
import com.googlecode.gaal.preprocess.api.Tokenizer;
import com.googlecode.gaal.preprocess.impl.RegexTokenizer;
import com.googlecode.gaal.suffix.api.EmbeddedSuffixTree;
import com.googlecode.gaal.suffix.api.EnhancedSuffixArray;
import com.googlecode.gaal.suffix.api.IntervalTree;
import com.googlecode.gaal.suffix.api.IntervalTree.Interval;
import com.googlecode.gaal.suffix.api.LinearizedSuffixTree;
import com.googlecode.gaal.suffix.api.SuffixArray;
import com.googlecode.gaal.suffix.impl.EmbeddedSuffixTreeImpl;
import com.googlecode.gaal.suffix.impl.EnhancedSuffixArrayImpl;
import com.googlecode.gaal.suffix.impl.LinearizedSuffixTreeImpl;

public class Visualizer {

    public static final String LATEX_HEADER = "\\documentclass[a4paper]{scrartcl}\n\\usepackage[utf8]{inputenc}\n"
            + "\\usepackage[UKenglish]{babel}\n\\usepackage{tikz}\n\\usepackage{caption}\n\\usetikzlibrary{arrows}\n"
            + "\\usetikzlibrary{shapes.arrows}\n\\usetikzlibrary{shadows}\n\\usetikzlibrary{positioning}\n\\begin{document}\n";

    public static final String LATEX_FOOTER = "\\end{document}\n";

    public static final String LATEX_INPUT = "\\input{%s}\n";

    public static final String TEXT = "mining␣engineering#";
    public static final String[] ALPHABET = { null, "e", "g", "i", "m", "n", "r", "␣", "\\#" };

    public static final String SRC_FILE_NAME = "data/vis-toy.en";
    public static final String DST_FILE_NAME = "data/vis-toy.de";
    // public static final String EN_FILE_NAME = "data/vis.en";

    public static final Corpus<String> CORPUS;
    static {
        Tokenizer<String> tokenizer = new RegexTokenizer(new StringReader(TEXT), "[\\W\\w]", new LaTeXNormailzer());
        CORPUS = new TreeMapCorpus(tokenizer, ALPHABET);
    }

    private static final String DOC_PATH = "doc/";
    private static final String TEST_FILE_NAME = "test.tex";
    private static final String TEX_EXT = ".tex";
    private static final String SEQUENCE = "sequence";
    private static final String SYMBOL = "symbol";
    private static final String SUBSEQUENCE = "subsequence";
    private static final String EQUIVALENCE = "equivalence";
    private static final String PREFIX = "prefix";
    private static final String SUFFIX = "suffix";
    private static final String REPEAT = "repeat";
    private static final String NON_RMAX_REPEAT = "nonrmaxrepeat";
    private static final String RMAX_REPEAT = "rmaxrepeat";
    private static final String SMAX_REPEAT = "smaxrepeat";
    private static final String SUFFIXES = "suffixes";
    private static final String SUFTAB = "suftab";
    private static final String LCPTAB = "lcptab";
    private static final String SUFFIX_ARRAY = "sa";
    private static final String INTERVAL_TREE = "itree";
    private static final String SUFFIX_TREE = "stree";
    private static final String CHILD_TABLE = "cldtab";
    private static final String ENHANCED_SUFFIX_ARRAY = "esa";
    private static final String BWT_TABLE = "bwttab";
    private static final String LINEARIZED_SUFFIX_TREE = "lst";
    private static final String NEW_CHILD_TABLE = "newcldtab";
    private static final String BINARY_INTERVAL_TREE = "bitree";
    private static final String DSUBSEQUENCE = "dsubsequence";
    private static final String ISUBSEQUENCE = "isubsequence";
    private static final String DREPEAT = "drepeat";
    private static final String EMBEDDED_SUFFIXES = "esuffixes";
    private static final String WINDOW = "window";
    private static final String ISUFTAB = "isuftab";
    private static final String EMBEDDED_SUFFIXES_WINDOW = "ewinsuffixes";
    private static final String EMBEDDED_SUFTAB = "esuftab";
    private static final String EMBEDDED_LCPTAB = "elcptab";
    private static final String EMBEDDED_SUFFIX_TREE = "est";
    private static final String EMBEDDED_INTERVAL_TREE = "etree";
    private static final String COR = "corpus";
    private static final String DOCS = "docs";
    private static final String PCOR = "pcorpus";
    private static final String PDOCS = "pdocs";
    private static final String TDMATRIX = "tdmatrix";
    private static final String WCMATRIX = "wcmatrix";
    private static final String RSPACE = "rspace";
    private static final String VECTORS = "vectors";
    private final Appendable buffer;
    private final Corpus<String> corpus;

    private Visualizer(Appendable buffer, Corpus<String> corpus) {
        this.buffer = buffer;
        this.corpus = corpus;
    }

    private void visualizeSequence(String fileName) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LaTeXVisualizer.visualizeSequence(out, corpus.sequence(), corpus);
        out.flush();
        out.close();
    }

    private void visualizeSymbol(String fileName) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LaTeXVisualizer.visualizeSubsequence(out, corpus.sequence(), corpus, 4);
        out.flush();
        out.close();
    }

    private void visualizeSubsequence(String fileName) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LaTeXVisualizer.visualizeSubsequence(out, corpus.sequence(), corpus, 3, 4, 5);
        out.flush();
        out.close();
    }

    private void visualizeEquivalence(String fileName) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LaTeXVisualizer.visualizeSubsequence(out, corpus.sequence(), corpus, 3, 4, 5, 15, 16, 17);
        out.flush();
        out.close();
    }

    private void visualizePrefix(String fileName) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LaTeXVisualizer.visualizeSubsequence(out, corpus.sequence(), corpus, 0, 1, 2, 3);
        out.flush();
        out.close();
    }

    private void visualizeSuffix(String fileName) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LaTeXVisualizer.visualizeSubsequence(out, corpus.sequence(), corpus, 15, 16, 17, 18);
        out.flush();
        out.close();
    }

    private void visualizeRepeat(String fileName, String[] labels, int length, int windowSize) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        visualizeInterval(out, lst, labels, 0, length, windowSize);
        out.flush();
        out.close();
    }

    private Interval findInterval(IntervalTree<? extends Interval> tree, String label) {
        Iterator<? extends Interval> iterator = tree.preorderIterator();
        while (iterator.hasNext()) {
            Interval interval = iterator.next();
            if (corpus.toString(interval.label(), "").equals(label)) {
                return interval;
            }
        }
        return null;
    }

    private <T extends SuffixArray & IntervalTree<? extends Interval>> void visualizeInterval(Writer out, T tree,
            String[] labels, int labelIndex, int length, int windowSize) throws IOException {
        Interval interval = findInterval(tree, labels[labelIndex]);
        if (labelIndex == labels.length - 1) {
            LaTeXVisualizer.visualizeInterval(out, null, null, tree, interval, length, windowSize, corpus);
        } else {
            EmbeddedSuffixTree est = EmbeddedSuffixTreeImpl.create(tree, interval, 5, corpus);
            visualizeInterval(out, est, labels, labelIndex + 1, length, windowSize);
        }
    }

    private void visualizeRepeat(String fileName) throws IOException {
        visualizeRepeat(fileName, new String[] { "ng" }, -1, 5);
    }

    private void visualizeNonRightMaximalRepeat(String fileName) throws IOException {
        visualizeRepeat(fileName, new String[] { "in" }, 1, 5);
    }

    private void visualizeRightMaximalRepeat(String fileName) throws IOException {
        visualizeRepeat(fileName, new String[] { "in" }, -1, 5);
    }
    
    private void visualizeSupermaximalRepeat(String fileName) throws IOException {
        visualizeRepeat(fileName, new String[] { "ing" }, -1, 5);
    }

    private void visualizeDiscontinuousRepeat(String fileName) throws IOException {
        visualizeRepeat(fileName, new String[] { "in", "ing" }, -1, 5);
    }

    private void visualizeSuffixes(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LaTeXVisualizer.visualizeSuffixes(out, caption, label, corpus.sequence(), corpus);
        out.flush();
        out.close();
    }

    private void visualizeSuffixTable(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeSuffixTable(out, caption, label, lst, corpus.sequence(), corpus);
        out.flush();
        out.close();
    }

    private void visualizeLcpTable(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeLcpInSuffixTable(out, caption, label, lst, corpus, false);
        out.flush();
        out.close();
    }

    private void visualizeSuffixArray(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeSuffixArray(out, caption, label, lst, corpus);
        out.flush();
        out.close();
    }

    private void visualizeIntervalTree(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        EnhancedSuffixArray esa = new EnhancedSuffixArrayImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeIntervalTree(out, caption, label, esa, null, corpus);
        out.flush();
        out.close();
    }

    private void visualizeSuffixTree(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        EnhancedSuffixArray esa = new EnhancedSuffixArrayImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeSuffixTree(out, caption, label, esa, corpus);
        out.flush();
        out.close();
    }

    private void visualizeChildTable(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        StringBuilder sb = new StringBuilder();
        EnhancedSuffixArray esa = new EnhancedSuffixArrayImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeChildTable(sb, caption, label, esa, corpus);
        String fixed = sb.toString().replace("level 4", "complete tree");
        out.append(fixed.replace("(11.east)", "(11.south)"));
        out.flush();
        out.close();
    }

    private void visualizeEnhancedSuffixArray(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        EnhancedSuffixArray esa = new EnhancedSuffixArrayImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeEnhancedSuffixArray(out, caption, label, esa, corpus);
        out.flush();
        out.close();
    }

    private void visualizeMaximalIntervals(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        EnhancedSuffixArray esa = new EnhancedSuffixArrayImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeMaximalIntervals(out, caption, label, esa, corpus);
        out.flush();
        out.close();
    }

    private void visualizeLinearizedSuffixTree(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeLinearizedSuffixTree(out, caption, label, lst, corpus);
        out.flush();
        out.close();
    }

    private void visualizeNewChildTable(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        StringBuilder sb = new StringBuilder();
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeChildTable(sb, caption, label, lst, corpus);
        String fixed = sb.toString().replace("(4.east)", "(4.south)");
        fixed = fixed.replace("(28.east)", "(28.south)");
        fixed = fixed.replace("level 8", "complete tree");
        out.append(fixed.replace("(7.east)", "(7.south)"));
        out.flush();
        out.close();
    }

    private void visualizeBinaryIntervalTree(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeIntervalTree(out, caption, label, lst, null, corpus);
        out.flush();
        out.close();
    }

    private void visualizeDiscontinuousSubsequence(String fileName) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LaTeXVisualizer.visualizeSubsequence(out, corpus.sequence(), corpus, 10, 11, 15, 16, 17);
        out.flush();
        out.close();
    }

    private void visualizeInterveningSubsequence(String fileName) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LaTeXVisualizer.visualizeComplexSubsequence(out, corpus.sequence(), corpus, 1, 0, 2, 0, 3, 2, 4, 2, 8, 1, 9, 1,
                16, 0, 17, 0);
        out.flush();
        out.close();
    }

    private void visualizeEmbeddedSuffixes(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        int windowSize = 5;
        Interval interval = findInterval(lst, "in");
        LaTeXVisualizer.visualizeEmbeddedSuffixes(out, caption, label, lst, interval, windowSize, corpus);
        out.flush();
        out.close();
    }

    private void visualizeWindow(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        int windowSize = 5;
        Interval interval = findInterval(lst, "in");
        LaTeXVisualizer.visualizeWindow(out, caption, label, lst, interval, windowSize, corpus);
        out.flush();
        out.close();
    }

    private void visualizeInverseSuffixTable(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        SuffixArray sa = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        LaTeXVisualizer.visualizeInverseSuffixTable(out, caption, label, sa, corpus);
        out.flush();
        out.close();
    }

    private void visualizeEmbeddedSuffixesInWindow(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        int windowSize = 5;
        Interval interval = findInterval(lst, "in");
        LaTeXVisualizer.visualizeEmbeddedSuffixesInWindow(out, caption, label, lst, interval, windowSize, corpus);
        out.flush();
        out.close();
    }

    private void visualizeEmbeddedSuffixTable(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        int windowSize = 5;
        Interval interval = findInterval(lst, "in");
        EmbeddedSuffixTree est = EmbeddedSuffixTreeImpl.create(lst, interval, windowSize, corpus);
        LaTeXVisualizer.visualizeEmbeddedSuffixTable(out, caption, label, est, corpus);
        out.flush();
        out.close();
    }

    private void visualizeEmbeddedLcpTable(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        int windowSize = 5;
        Interval interval = findInterval(lst, "in");
        EmbeddedSuffixTree est = EmbeddedSuffixTreeImpl.create(lst, interval, windowSize, corpus);
        LaTeXVisualizer.visualizeLcpInSuffixTable(out, caption, label, est, corpus, true);
        out.flush();
        out.close();
    }

    private void visualizeEmbeddedSuffixTree(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        int windowSize = 5;
        Interval interval = findInterval(lst, "in");
        EmbeddedSuffixTree est = EmbeddedSuffixTreeImpl.create(lst, interval, windowSize, corpus);
        LaTeXVisualizer.visualizeEmbeddedSuffixTree(out, caption, label, est, corpus);
        out.flush();
        out.close();
    }

    private void visualizeEmbeddedIntervalTree(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        LinearizedSuffixTree lst = new LinearizedSuffixTreeImpl(corpus.sequence(), corpus.alphabetSize());
        int windowSize = 5;
        Interval interval = findInterval(lst, "in");
        EmbeddedSuffixTree est = EmbeddedSuffixTreeImpl.create(lst, interval, windowSize, corpus);
        LaTeXVisualizer.visualizeIntervalTree(out, caption, label, est, null, corpus);
        out.flush();
        out.close();
    }

    private void visualizeCorpus(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        int windowSize = 5;
        LaTeXVisualizer.visualizeCorpus(out, caption, label, SRC_FILE_NAME, DST_FILE_NAME, windowSize);
        out.flush();
        out.close();
    }

    private void visualizeDocuments(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        int windowSize = 5;
        LaTeXVisualizer.visualizeDocuments(out, caption, label, SRC_FILE_NAME, DST_FILE_NAME, windowSize);
        out.flush();
        out.close();
    }

    private void visualizeParallelCorpus(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        int windowSize = 5;
        LaTeXVisualizer.visualizeParallelCorpus(out, caption, label, SRC_FILE_NAME, DST_FILE_NAME, windowSize);
        out.flush();
        out.close();
    }

    private void visualizeParallelDocuments(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        int windowSize = 5;
        LaTeXVisualizer.visualizeParallelDocuments(out, caption, label, SRC_FILE_NAME, DST_FILE_NAME, windowSize);
        out.flush();
        out.close();
    }

    private void visualizeTermDocumentMatrix(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        int windowSize = 5;
        LaTeXVisualizer.visualizeTermDocumentMatrix(out, caption, label, SRC_FILE_NAME, DST_FILE_NAME, windowSize);
        out.flush();
        out.close();
    }
    
    private void visualizeWordContextMatrix(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        int windowSize = 5;
        LaTeXVisualizer.visualizeWordContextMatrix(out, caption, label, SRC_FILE_NAME, DST_FILE_NAME, windowSize);
        out.flush();
        out.close();
    }

    private void visualizeRepeatSpace(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        int windowSize = 5;
        List<String> labels = Arrays.asList(new String[] { "sowohl$\\dots$als auch" });
        LaTeXVisualizer.visualizeRepeats(out, caption, label, SRC_FILE_NAME, DST_FILE_NAME, labels, windowSize);
        out.flush();
        out.close();
    }

    private void visualizeVectors(String fileName, String caption, String label) throws IOException {
        buffer.append(String.format(LATEX_INPUT, fileName));
        Writer out = new FileWriter(DOC_PATH + fileName);
        int windowSize = 5;
        LaTeXVisualizer.visualizeVectors(out, caption, label, SRC_FILE_NAME, DST_FILE_NAME, windowSize);
        out.flush();
        out.close();
    }

    public static void main(String[] args) throws IOException {
        Writer out = new FileWriter(DOC_PATH + TEST_FILE_NAME);
        out.append(LATEX_HEADER);
        Visualizer viz = new Visualizer(out, CORPUS);
        viz.visualizeSequence(SEQUENCE + TEX_EXT);
        viz.visualizeSymbol(SYMBOL + TEX_EXT);
        viz.visualizeSubsequence(SUBSEQUENCE + TEX_EXT);
        viz.visualizeEquivalence(EQUIVALENCE + TEX_EXT);
        viz.visualizePrefix(PREFIX + TEX_EXT);
        viz.visualizeSuffix(SUFFIX + TEX_EXT);
        viz.visualizeRepeat(REPEAT + TEX_EXT);
        viz.visualizeNonRightMaximalRepeat(NON_RMAX_REPEAT + TEX_EXT);
        viz.visualizeRightMaximalRepeat(RMAX_REPEAT + TEX_EXT);
        viz.visualizeSupermaximalRepeat(SMAX_REPEAT + TEX_EXT);
        viz.visualizeSuffixes(SUFFIXES + TEX_EXT, "The suffixes of the sequence $S$ sorted by index.", SUFFIXES);
        viz.visualizeSuffixTable(SUFTAB + TEX_EXT, "The $suftab$ array for the sequence $S$.", SUFTAB);
        viz.visualizeLcpTable(LCPTAB + TEX_EXT, "The $lcptab$ array for the sequence $S$.", LCPTAB);
        viz.visualizeSuffixArray(SUFFIX_ARRAY + TEX_EXT, "The suffix array for the sequence $S$.",
                SUFFIX_ARRAY);
        viz.visualizeIntervalTree(
                INTERVAL_TREE + TEX_EXT,
                "The lcp-interval tree with the $suftab$ and the $lcptab$ for the sequence $S$.",
                INTERVAL_TREE);
        viz.visualizeSuffixTree(SUFFIX_TREE + TEX_EXT, "The suffix tree for the sequence $S$.", SUFFIX_TREE);
        viz.visualizeChildTable(CHILD_TABLE + TEX_EXT, "lcp-interval tree traversal using the $cldtab$: level %d.",
                CHILD_TABLE + "%d");
        viz.visualizeEnhancedSuffixArray(ENHANCED_SUFFIX_ARRAY + TEX_EXT,
                "The enhanced suffix array for the sequence $S$.", ENHANCED_SUFFIX_ARRAY);
        viz.visualizeMaximalIntervals(BWT_TABLE + TEX_EXT,
                "Using Burrows-Wheeler transform table to find maximal repeats.", BWT_TABLE);
        viz.visualizeLinearizedSuffixTree(LINEARIZED_SUFFIX_TREE + TEX_EXT,
                "The linearized suffix tree for the sequence $S$", LINEARIZED_SUFFIX_TREE);
        viz.visualizeBinaryIntervalTree(
                BINARY_INTERVAL_TREE + TEX_EXT,
                "The binary lcp-interval tree with the $suftab$ and the $lcptab$ for the sequence $S$.",
                BINARY_INTERVAL_TREE);
        viz.visualizeNewChildTable(NEW_CHILD_TABLE + TEX_EXT,
                "Binary lcp-interval tree traversal using the \\textit{newcldtab}: level %d.", NEW_CHILD_TABLE + "%d");
        viz.visualizeDiscontinuousSubsequence(DSUBSEQUENCE + TEX_EXT);
        viz.visualizeInterveningSubsequence(ISUBSEQUENCE + TEX_EXT);
        viz.visualizeDiscontinuousRepeat(DREPEAT + TEX_EXT);
        viz.visualizeEmbeddedSuffixes(
                EMBEDDED_SUFFIXES + TEX_EXT,
                "The section of the \\textit{suftab} corresponding to the interval $[6..9]$, the embedded suffixes are highlighted.",
                EMBEDDED_SUFFIXES);
        viz.visualizeWindow(WINDOW + TEX_EXT,
                "A window of size 5 applied to the embedded suffixes in Figure \\ref{fig:" + EMBEDDED_SUFFIXES + "}.",
                WINDOW);
        viz.visualizeInverseSuffixTable(ISUFTAB + TEX_EXT, "The suffix table and the inverse suffix table for $S$.", ISUFTAB);
        viz.visualizeEmbeddedSuffixesInWindow(EMBEDDED_SUFFIXES_WINDOW + TEX_EXT,
                "The embedded suffixes in Figure \\ref{fig:" + EMBEDDED_SUFFIXES
                        + "} extended by all the suffixes from the window in Figure \\ref{fig:" + WINDOW + "}.",
                EMBEDDED_SUFFIXES_WINDOW);
        viz.visualizeEmbeddedSuffixTable(EMBEDDED_SUFTAB + TEX_EXT,
                "The embedded \\textit{suftab} array for the interval $[6..9]$.", EMBEDDED_SUFTAB);
        viz.visualizeEmbeddedLcpTable(EMBEDDED_LCPTAB + TEX_EXT,
                "The embedded \\textit{lcptab} array for the interval $[6..9]$.", EMBEDDED_LCPTAB);
        viz.visualizeEmbeddedSuffixTree(EMBEDDED_SUFFIX_TREE + TEX_EXT,
                "The embedded suffix tree for the interval $[6..9]$", EMBEDDED_SUFFIX_TREE);
        viz.visualizeEmbeddedIntervalTree(EMBEDDED_INTERVAL_TREE + TEX_EXT,
                "The embedded binary lcp-interval tree for the interval $[6..9]$.", EMBEDDED_INTERVAL_TREE);
        viz.visualizeCorpus(COR + TEX_EXT, "A corpus after preprocessing.", COR);
        viz.visualizeDocuments(DOCS + TEX_EXT, "A corpus split into documents.", DOCS);
        viz.visualizeParallelCorpus(PCOR + TEX_EXT, "A parallel corpus after preprocessing.", PCOR);
        viz.visualizeParallelDocuments(PDOCS + TEX_EXT, "A parallel corpus split into documents.", PDOCS);
        viz.visualizeTermDocumentMatrix(TDMATRIX + TEX_EXT, "A term-document matrix.", TDMATRIX);
        viz.visualizeWordContextMatrix(WCMATRIX + TEX_EXT, "A word-context matrix.", WCMATRIX);
        viz.visualizeRepeatSpace(RSPACE + TEX_EXT, "Repeat vectors in document space.", RSPACE);
        viz.visualizeVectors(VECTORS + TEX_EXT, "Source and target repeat vector comparison.", VECTORS);
        out.append(LATEX_FOOTER);
        out.flush();
        out.close();
    }
}
